package com.tools.web;

import com.tools.common.object.Note;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.Objects;

/**
 * Spring 手动事务包装实例
 * */
@Note("Spring 手动事务包装实例")
public class SpringManualTransaction {

    @Note("事务管理对象")
    private final DataSourceTransactionManager transactionManager;

    @Note("定义事务的传播行为和隔离级别")
    private final TransactionDefinition transactionDefinition;

    public SpringManualTransaction(DataSourceTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
        if(transactionManager == null) throw new NullPointerException("DataSourceTransactionManager 不能为 null");
        if(transactionDefinition == null) throw new NullPointerException("TransactionDefinition 不能为 null");
        this.transactionManager = transactionManager;
        this.transactionDefinition = transactionDefinition;
    }

    public SpringManualTransaction(DataSourceTransactionManager transactionManager) {
        this(transactionManager, new DefaultTransactionDefinition());
    }

    @Note("isolationLevel 事务的隔离级别，可以通过 TransactionDefinition.ISOLATION_XXX 使用定义好的常量。" +
            "propagationBehavior 事务的传播行为，可以通过 TransactionDefinition.PROPAGATION_XXX 使用定义好的常量")
    public SpringManualTransaction(DataSourceTransactionManager transactionManager, int isolationLevel, int propagationBehavior) {
        if(transactionManager == null) throw new NullPointerException("DataSourceTransactionManager 不能为 null");
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        definition.setIsolationLevel(isolationLevel);
        definition.setPropagationBehavior(propagationBehavior);
        this.transactionManager = transactionManager;
        this.transactionDefinition = definition;
    }


    public SpringManualTransaction(ApplicationContext context) {
        this.transactionManager = context.getBean(DataSourceTransactionManager.class);
        this.transactionDefinition = context.getBean(TransactionDefinition.class);
    }


    public DataSourceTransactionManager getTransactionManager() {
        return transactionManager;
    }

    public TransactionDefinition getTransactionDefinition() {
        return transactionDefinition;
    }

    public TransactionStatus startTransaction() {
        return this.transactionManager.getTransaction(this.transactionDefinition);
    }

    public TransactionStatus startTransaction(TransactionDefinition transactionDefinition) {
        if(transactionDefinition == null) throw new NullPointerException("TransactionDefinition 不能为 null");
        return this.transactionManager.getTransaction(transactionDefinition);
    }

    public void commit(TransactionStatus status) {
        this.transactionManager.commit(status);
    }

    public void rollback(TransactionStatus status) {
        this.transactionManager.rollback(status);
    }

    @Override
    public String toString() {
        return "SpringManualTransaction{" +
                "transactionManager=" + transactionManager +
                ", transactionDefinition=" + transactionDefinition +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SpringManualTransaction that = (SpringManualTransaction) o;
        return Objects.equals(transactionManager, that.transactionManager) && Objects.equals(transactionDefinition, that.transactionDefinition);
    }

    @Override
    public int hashCode() {
        return Objects.hash(transactionManager, transactionDefinition);
    }
}
